import java.util.Timer;
import java.util.concurrent.PriorityBlockingQueue;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 26727
 * Date: 2024-05-21
 * Time: 20:07
 */
//表示一个任务
class MyTask implements Comparable<MyTask>{
    public Runnable runnable;
    //为了方便后续判断使用绝对的时间戳
    public long time;


    public MyTask(Runnable runnable, long delay) {
        this.runnable = runnable;
        //取当前时刻的时间戳+delay作为该任务实际执行的时间戳
        this.time = System.currentTimeMillis()+delay;
    }

    @Override
    public int compareTo(MyTask o) {
        return (int)(this.time-o.time);
        //取时间最小的元素
    }
}
class MyTimer {
    //创建一个锁对象
    private Object locker = new Object();

    //这个结构就是带有优先级的阻塞队列 核心数据结构
    private PriorityBlockingQueue<MyTask> queue = new PriorityBlockingQueue<>();
    //此处delay是一个形如3000这样的数字(多长时间之后执行该任务)
    //这列的元素需要手动封装
    //创建一个类 表示两方面 1.执行的任务是啥 2.任务啥时候执行
    public void schedule(Runnable runnable, long delay) {
        //根据参数构造MyTask，插入队列即可
        MyTask myTask = new MyTask(runnable,delay);
        queue.put(myTask);
        synchronized (locker) {
            locker.notify();
        }
    }

    //在这里构造一个线程负责执行具体任务
    public MyTimer() {
        Thread t = new Thread(() -> {
           while(true) {
               try {
                   synchronized (locker) {
                       //阻塞队列只有阻塞的入队列和阻塞的出队列，没有阻塞的查看队首元素
                       MyTask myTask = queue.take();
                       //当前队列无元素 队列阻塞 退出循环
                       //队列有元素就可以获取到元素
                       //看钱当前任务时间是否合适
                       long curTime = System.currentTimeMillis();
                       if (myTask.time <= curTime) {
                           //时间到了可以执行任务了
                           myTask.runnable.run();
                       } else {
                           //时间没到
                           //把刚才取出的任务重新塞回队列中
                           queue.put(myTask);
                           //实时时间进行调整
                           locker.wait(myTask.time-curTime);
                       }
                   }
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
           }
        });
        t.start();
    }
}
public class ThreadDemo20 {
    public static void main(String[] args) {
        MyTimer myTimer = new MyTimer();
        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hi4");
            }
        },4000);

        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hi3");
            }
        },3000);

        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hi2");
            }
        },2000);

        myTimer.schedule(new Runnable() {
            @Override
            public void run() {
                System.out.println("hi1");
            }
        },1000);

        System.out.println("hi0");
    }
}
